Implementing GDPR in ASP.NET Core
General Data Protection Regulation
When browsing the web, if you see a message like "This website uses cookies, do you accept?", this stems from the "General Data Protection Regulation (GDPR)" passed by the European Union on April 27, 2016, which became enforceable on May 25, 2018. Its purpose is to regulate the data and privacy of EU individuals. For the full content, please refer to Wiki GDPR.
In addition to the EU's GDPR, the U.S. state of California has similar regulations, such as the California Consumer Privacy Act (CCPA) and the California Online Privacy Protection Act (CalOPPA).
Implementation Methods
Create a Privacy Policy page: If you use Visual Studio to create a .NET Core 2.1 or later Web project, you will find an additional "Privacy" page. This is used to display the website's Privacy Policy. For an example of a privacy policy, you can refer to the Chinese Privacy Policy Template for Websites. According to the author, this is a version adjusted based on the "Government Website Layout and Content Management Guidelines." However, I could not find the original template. For commercial use, it is best to verify whether the content complies with regulations like GDPR.
Displaying cookie-related messages on the webpage:
- Provide a link to the "Privacy and Cookie Policy" page.
- Ask for consent to the policy. Approaches generally fall into the following categories:
- No explicit prompt: Simply inform the user that continuing to use the site implies consent to the privacy policy, and provide a "Close" button.
- Inform the user that continuing to use the site implies consent, and provide both "Accept" and "Close" buttons.
- Do not assume consent by continued browsing, and provide both "Accept" and "Close" buttons.
- Categorize the types of cookies used on the site, allowing users to consent only to necessary cookies. "Stack Overflow" is an example of this. If you are interested, you can browse in incognito mode to see that they provide a "Customize settings" button, allowing you to adjust the types of cookies you allow.
- Handling the dismissal of the prompt message:
- Dismiss: Only hides the message temporarily; it will reappear when the page is reloaded.
- Accept: Write a flag to a cookie. When this cookie exists, the prompt message is no longer displayed, and subsequent actions can be taken based on this flag to decide whether to write other cookies.
Methods for not writing cookies until the user consents: Some sites inform users that "continuing to use this site implies consent to the privacy policy" because they do not want to handle the logic of stopping cookie writes. Therefore, they default to user consent and explain in the privacy policy that users can adjust browser settings to block cookies. Of course, reasonably speaking, non-essential cookies should be stopped until the user provides consent.
Implementing this part is not difficult. Instead of using the native framework API, you can write a Facade to encapsulate it. Only call the native API when the user's consent cookie is present.
For MVC, the simplest approach is to write a
BasicControllerthat other controllers inherit from, using itsAddCookiemethod to add aResponse Cookie. An example is as follows:
public abstract BasicController {
public void AddCookie(HttpCookie cookie) {
// Please adjust the Cookie Name and Value according to your actual situation
if (Request.Cookies["UseCookies"] == "yes") {
Response.Cookies.Add(cookie);
}
}
}Implementation using ASP.NET Core
The .NET Core 2.1 project template already includes a GDPR implementation (excluding the privacy policy content). However, in subsequent versions (I haven't tested which specific version, but MSDN states it is provided in templates after 2.2), the page implementation was removed, leaving only the API. Nevertheless, a GDPR implementation example is provided on MSDN. Basically, besides needing to adjust the HTML to match your UI framework and updating the text according to your policy (you also need to adjust it if you don't use jQuery, as the code uses native DOM APIs but still includes $.ready()), this section focuses on explaining the official example.
Below, I use "Consent" to represent the cookie for "Allow Cookie Usage Settings."
Program.cs
builder.Services.Configure<CookiePolicyOptions>(options => {
// If set to true, "Consent" is required to set non-essential cookies
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
// ...other code...
app.UseCookiePolicy(); // Cookie-related middleware is configured here
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
app.Run();_CookieConsentPartial.cshtml
- The default Injection Instance type for
ITrackingConsentFeatureis ResponseCookiesWrapper (the specific DI behavior occurs atapp.UseCookiePolicy()). - The value of
consentFeature?.CanTrackistrueifCookiePolicyOptions.CheckConsentNeeded(HttpContext)istrueand the "Consent" cookie exists. In other words, ifCheckConsentNeeded = context => falseis set inProgram.cs, the reminder will not be displayed. consentFeature?.CreateConsentCookie()is used to create the text for the "Consent" cookie. The content is roughly.AspNet.Consent=yes; expires={date}; path=/; secure. The "Consent" cookie is not actually created here, but rather whendocument.cookie = button.dataset.cookieString;is executed.
@using Microsoft.AspNetCore.Http.Features
@{
var consentFeature = Context.Features.Get<ITrackingConsentFeature>();
var showBanner = !consentFeature?.CanTrack ?? false;
var cookieString = consentFeature?.CreateConsentCookie();
}
@if (showBanner) {
<div id="cookieConsent" class="alert alert-info alert-dismissible fade show" role="alert">
Use this space to summarize your privacy and cookie use policy. <a asp-page="/Privacy">Learn More</a>.
<button type="button" class="accept-policy close" data-dismiss="alert" aria-label="Close" data-cookie-string="@cookieString">
<span aria-hidden="true">Accept</span>
</button>
</div>
<script>
(function () {
var button = document.querySelector("#cookieConsent button[data-cookie-string]");
button.addEventListener("click", function (event) {
document.cookie = button.dataset.cookieString;
}, false);
})();
</script>
}Essential Cookies
Some cookies are non-essential, such as those for preferences that optimize the user experience. However, some cookies affect the normal operation of the website. If you want the site to function normally even if the user has not consented to cookie usage (the prompt message should ideally explain this situation), such cookies should be set with IsEssential = true.
Response.Cookies.Append("name", "value", new CookieOptions {
IsEssential = true // Indicates that this cookie is essential
});Change Log
- 2022-10-27 Initial document creation.